/**
 * @method FilterTool
 * @description 检索组件
 *  @props {Number} colNum 展示成几列
 *  @props {Array} data 构成检索的每一个元素
 *  @props {Function} getFilterData 动态获取 构成检索的每一个元素,当有这个参数，就不会用data,主要为了实现动态获取当前时间，否则defaultValue不会改变
 *  @props {Boolean} isOnChange  true: 改变检索条件就搜索并且无搜索按钮，默认:false
 *  @props {Function} query 点击查询按钮后的回调函数
 *  @props {Function} refreshFilter 筛选条件事件触发之后的回调
 *  @props {Function} refresh 刷新重置回调函数，如果有这个，就会显示刷新按钮
 *  @props {Array} columns 自定义列，如果有这个，就会显示设置按钮
 *  @props {Function} setColumn 自定义列的回调
 *  @props {Function} defaultColumns 默认的自定义列
 *  @props {Boolean}  isSearchNotSpaceBetween  是否将search 和其他过滤条件左右对齐排列，默认true
 *
 */

import React, { Component } from 'react';
import { Row, Col, Input, DatePicker, Select, Switch, Icon, Dropdown, Menu, Tooltip, message, Button } from 'antd';
import moment from 'moment';
import 'moment/locale/zh-cn';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import { randomKey } from '../../utils/utils';
import SearchTool from '../SearchTool';
import { IconFont } from '../IconFont';
import SetColumn from '../SetColumn';
import Modal from '../Modal';

import './index.less';
moment.locale('zh-cn');
const Option = Select.Option;
const { RangePicker } = DatePicker;

class FilterTool extends Component {
  constructor(props) {
    super(props);
    this.state = {
      filter: {},
      label: {},
      expended: false,
      searchKey: 0,
    };
    this.filterRange = {};
    this.keys = [];
    this.columnSet = React.createRef();
    this.responsive = {
      xs: 12,
      sm: 8,
      md: 8,
      lg: 6,
      xl: 4,
    };
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.reload && !this.props.reload) {
      this.initFilterValue();
    }
    // 修改部分参数
    if (nextProps.initParams && !this.props.initParams) {
      this.initSomeValue(nextProps.initParams);
    }
  }
  componentDidMount() {
    this.initFilterValue();
  }

  initSomeValue = (initParams) => {
    const { filter } = this.state;
    this.setState({
      filter: {
        ...filter,
        ...initParams,
      },
    });
  };

  initFilterValue = (isInit) => {
    this.keys = [];
    const { data, getFilterData } = this.props;
    const filter = {};
    const label = {};
    const fData = getFilterData ? getFilterData() : data;
    fData.forEach((item) => {
      // 判断各种异常情况
      if (!item.key) {
        console.error('data的各项中，必须指定key');
        return;
      }
      if (this.keys.includes(item.key)) {
        console.error(`key值有重复`);
        return;
      }

      this.keys.push(item.key); // 插入数组，可判断是否有重复

      // 如果label是个数组，则label可切换
      if (item.label instanceof Array && item.label.length > 0) {
        if (item.type.toLowerCase() === 'rangepicker') {
          console.error(`label切换不支持Rangepicker类型`);
          return;
        }
        const it = this.state.label[item.key]
          ? {
              value: this.state.label[item.key][0],
              name: this.state.label[item.key][1],
            }
          : item.label[0];
        filter[it.value] = item.defaultValue; // 默认取一组
        label[item.key] = [it.value, it.name];
      } else {
        if (!item.name) {
          console.error(`name不能为空`);
          return;
        }
      }
      //如果是数组
      if (item.name && item.name instanceof Array && item.defaultValue instanceof Array) {
        if (item.defaultValue.length !== item.name.length) {
          console.error('默认值指定的数组长度与name指定的数组长度不一致');
          return;
        }
        item.name.forEach((it, i) => {
          filter[it] = isInit && item.initValue !== undefined ? item.initValue[i] || '' : item.defaultValue[i] || '';
        });
      }
      if (item.name && item.name instanceof Array && item.placeholder instanceof Array && !item.defaultValue) {
        if (item.placeholder.length !== item.name.length) {
          console.error('默认值指定的数组长度与name指定的数组长度不一致');
          return;
        }
        item.name.forEach((it, i) => {
          filter[it] = isInit && item.initValue !== undefined ? item.initValue[i] || '' : '';
        });
      }
      if (item.name && typeof item.name === 'string') {
        filter[item.name] = isInit && item.initValue !== undefined ? item.initValue : item.defaultValue || '';
      }
    });
    this.setState(
      {
        filter,
        label,
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params);
      }
    );
  };

  handleTargetChange = (key, e) => {
    this.setState(
      {
        filter: {
          ...this.state.filter,
          [key]: e.target.value,
        },
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params);
      }
    );
  };
  handleChange = (key, value, onChange) => {
    try {
      onChange && onChange(key, value);
    } catch (err) {
      if (err !== 'false') {
        message.warning(err);
      }
      console.log(err);
      return;
    } finally {
    }

    this.setState(
      {
        filter: {
          ...this.state.filter,
          [key]: value,
        },
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params, key);
      }
    );
  };

  onChangeSearch = (key, value) => {
    this.setState(
      {
        filter: {
          ...this.state.filter,
          [key]: value,
        },
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params, false);
      }
    );
  };

  onSwitch = (key, value) => {
    this.setState(
      {
        filter: {
          ...this.state.filter,
          [key]: !this.state.filter[key],
        },
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params);
      }
    );
  };
  onChangeDate = (name, value, dateString) => {
    const start = name[0];
    const end = name[1];
    this.setState(
      {
        filter: {
          ...this.state.filter,
          [start]: dateString[0],
          [end]: dateString[1],
        },
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params);
      }
    );
  };
  onChangeDateRange = (name, format, value, dateString) => {
    const start = name[0];
    const end = name[1];
    this.setState(
      {
        filter: {
          ...this.state.filter,
          [start]: dateString[0],
          [end]:
            moment(dateString[1]).valueOf() - moment().valueOf() > 0
              ? moment().format(format || 'YYYY-MM-DD HH:mm:ss')
              : dateString[1],
        },
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params, false); // 只更新页面参数，不刷新
      }
    );
  };
  onDateOk = () => {
    setTimeout(() => {
      const params = this.getParams();
      this.props.refreshFilter(params);
    });
  };
  getParams = () => {
    const { filter } = this.state;
    // const filterFk = { ...filter, ...this.filterRange };
    const filterFk = filter;
    const params = {};
    Object.keys(filterFk).forEach((key) => {
      if (filterFk[key] !== undefined && filterFk[key] !== '') {
        params[key] = filterFk[key];
      }
    });
    return params;
  };
  handleSubmit = () => {
    const params = this.getParams();
    this.props.refreshFilter(params);
    this.props.query();
  };
  reset = () => {
    if (this.props.reset) {
      this.props.reset();
    }
    this.initFilterValue(true);
  };
  refreshNow = () => {
    this.reset();
    this.setState({
      searchKey: randomKey(),
    });
    this.props.refresh();
  };
  getFormItem = (item) => {
    const { filter, label } = this.state;
    const type = item.type.toLowerCase();
    const labelKey = (label[item.key] && label[item.key][0]) || '';
    const name = item.label instanceof Array && item.label.length > 0 ? labelKey : item.name; // {label[item.key][1]}
    switch (type) {
      case 'input':
        return (
          <Input
            onChange={item.onChange ? item.onChange.bind(this, name) : this.handleTargetChange.bind(this, name)}
            value={filter[name]}
            placeholder={item.placeholder}
          />
        );
      case 'search':
        return (
          <>
            <div>
              <SearchTool
                key={this.state.searchKey}
                search={this.handleChange.bind(this, name)}
                placeholder={item.placeholder}
                disabled={this.props.disabled}
                value={item.defaultValue}
                change={this.onChangeSearch.bind(this, name)}
              />
            </div>
            {/* {this.props.refresh && (
              <Tooltip title={'重置'}>
                <IconFont
                  type='icon-refresh1'
                  className='color-default'
                  style={{ fontSize: '16px', marginLeft: '10px', cursor: 'pointer' }}
                  onClick={this.refreshNow}
                />
              </Tooltip>
            )}
            {this.props.columns && (
              <Tooltip title={'自定义列表项'}>
                <IconFont
                  type='iconsetting-1'
                  className='color-default'
                  style={{ fontSize: '16px', marginLeft: '10px', cursor: 'pointer' }}
                  onClick={() => this.openColumn()}
                />
              </Tooltip>
            )}
            {this.props.export && (
              <Tooltip title={this.props.exportMsg} placement='left'>
                <IconFont
                  type='icon-download1'
                  className='color-default'
                  style={{ fontSize: '16px', marginLeft: '10px', cursor: 'pointer' }}
                  onClick={() => this.props.export()}
                />
              </Tooltip>
            )} */}
          </>
        );
      case 'select':
        const mode = item.mode ? { mode: item.mode } : {};
        return (
          <Select
            className='prop-select'
            onChange={(value) => {
              this.handleChange(name, value, item.onChange);
            }}
            // onChange={item.onChange ? item.onChange.bind(this, name) : this.handleChange.bind(this, name)}
            value={filter[name] || (mode.mode === 'multiple' ? [] : undefined) || item.defaultValue}
            style={{ width: item.width || '100%' }}
            allowClear={item.allowClear}
            disabled={this.props.disabled}
            placeholder={item.placeholder}
            {...mode}
          >
            {item.options &&
              item.options.map((item, index) => {
                return (
                  <Option value={item.value} key={item.value}>
                    {item.name}
                  </Option>
                );
              })}
          </Select>
        );
      case 'rangepicker':
        return (
          <RangePicker
            showTime={
              item.showTime === false
                ? false
                : {
                    defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
                  }
            }
            format={item.format || 'YYYY-MM-DD HH:mm:ss'}
            placeholder={item.placeholder}
            onChange={
              item.onChange
                ? item.onChange.bind(this, name)
                : item.changeSubmit
                ? this.onChangeDate.bind(this, name)
                : this.onChangeDateRange.bind(this, name, item.format)
            }
            onOk={this.onDateOk}
            locale={locale}
            style={{ width: '100%' }}
            disabledDate={item.disabledDate ? item.disabledDate : this.disabledDate}
            ranges={item.ranges}
            allowClear={item.allowClear === undefined ? true : item.allowClear}
            disabled={this.props.disabled}
            value={
              !filter[item.name[0]] || !filter[item.name[1]]
                ? null
                : [moment(filter[item.name[0]]), moment(filter[item.name[1]])]
            }
          />
        );
      case 'switch':
        return (
          <Switch
            checkedChildren={item.checkedChildren || '是'}
            unCheckedChildren={item.unCheckedChildren || '否'}
            checked={filter[name]}
            onChange={item.onChange ? item.onChange.bind(this, name) : this.onSwitch.bind(this, name)}
            disabled={this.props.disabled}
          />
        );
      default:
        return (
          <Input
            onChange={item.onChange ? item.onChange.bind(this, name) : this.handleTargetChange.bind(this, name)}
            value={filter[name]}
            placeholder={item.placeholder}
            disabled={this.props.disabled}
          />
        );
    }
  };

  toggle = () => {
    this.setState({
      expended: !this.state.expended,
    });
  };

  disabledDate = (current) => {
    return current && current > moment().endOf('day');
  };

  removeOtherKeys = (obj, arr, key) => {};

  changeLabel = (item, e) => {
    const { filter } = this.state;
    const oldName = this.state.label[item.key][0];
    const curLabel = item.label.find((o) => o.value === e.key);
    delete filter[oldName];
    filter[e.key] = '';
    this.setState(
      {
        label: {
          ...this.state.label,
          [item.key]: [e.key, curLabel.name],
        },
        filter,
      },
      () => {
        const params = this.getParams();
        this.props.refreshFilter(params);
      }
    );
  };

  openColumn = () => {
    Modal.open({
      title: '自定义列表字段',
      width: '550px',
      content: (
        <SetColumn
          options={this.props.columns}
          defaultColumns={this.props.defaultColumns || undefined}
          createRef={this.columnSet}
        />
      ),
      isOkBtn: true,
      isCancelBtn: true,
      ok: () => {
        try {
          const value = this.columnSet.current.getValue();
          this.props.setColumn && this.props.setColumn(value);
          Modal.close();
        } catch (err) {
          message.warning(err);
        }
      },
      cancel: () => {
        Modal.close();
      },
    });
  };

  renderFilter = (data, label, colNum) => {
    const span = colNum ? { span: 24 / colNum } : null; // 如果colNum存在，则自动分配宽度span
    return (
      <>
        {data.map((item, index) => {
          const formItem = this.getFormItem(item);
          const spanItem = item.span ? { span: item.span } : span;
          const colStyle = item.style ? item.style : {};
          return (
            <Col className='gutter-row filter-item' key={item.key || item.name} style={colStyle} {...spanItem}>
              {item.label && typeof item.label === 'string' && (
                <span className='filter-label' style={item.labelStyle ? item.labelStyle : null}>
                  {item.label}
                </span>
              )}
              {item.label && item.label instanceof Array && (
                <Dropdown
                  className='filter-label'
                  overlay={
                    <Menu>
                      {item.label.map((it) => {
                        return (
                          <Menu.Item key={it.value} onClick={this.changeLabel.bind(this, item)}>
                            {it.name}
                          </Menu.Item>
                        );
                      })}
                    </Menu>
                  }
                  trigger={['click']}
                >
                  <span>
                    {label && label[item.key] && label[item.key][1]}
                    <Icon type='down' />
                  </span>
                </Dropdown>
              )}
              {formItem}
            </Col>
          );
        })}
      </>
    );
  };
  getColResponsive(colspan) {
    const obj = {};
    for (const [key, val] of Object.entries(this.responsive)) {
      obj[key] = val * colspan;
    }
    return obj;
  }

  render() {
    const { data, getFilterData, justify, isSearchNotSpaceBetween, colNum, gutter } = this.props;
    const fData = getFilterData ? getFilterData() : data;
    const { label } = this.state;
    const leftData = !isSearchNotSpaceBetween ? fData.filter((item) => item.type.toLowerCase() !== 'search') : fData;
    const rightData = !isSearchNotSpaceBetween ? fData.filter((item) => item.type.toLowerCase() === 'search') : [];
    return (
      <div className='filter-form filter-form-new'>
        <Row span={20}>
          <Col style={{ float: 'right', textAlign: 'right' }}>
            <div className='searchbar-form-item'>
              <Button onClick={this.refreshNow} icon={'redo'}>
                重置
              </Button>
              <Button type='primary' icon={'filter'} style={{ marginLeft: '10px' }} onClick={this.handleSubmit}>
                查询
              </Button>
            </div>
          </Col>
          {fData.map((item) => {
            const formItem = this.getFormItem(item);
            return (
              <Col {...this.getColResponsive(item.colNum || 1)}>
                <div className='searchbar-form-item'>{formItem}</div>
              </Col>
            );
          })}
        </Row>
      </div>
    );
  }
}

export default FilterTool;
